import { defineStore } from 'pinia';
import { getRoot, setRoot, makeInitialData, patchRoot } from './useStorage';
import type { StorageModel, SearchEngine } from '../types/model';
import { uid } from '../utils/uid';
import { isValidTemplate } from '../utils/validators';
import { useSettings } from './useSettings'; // 直接导入
import { fetchEngineIconByTemplate } from '../utils/favicon';
import { LOGI, LOGW } from '../../../shared/log.js';

export const useEngines = defineStore('engines', {
  state: () => ({
    inited: false,
    list: [] as SearchEngine[],
    defaultId: 'baidu' as string,
  }),
  getters: {
    byId: (s) => new Map(s.list.map(e => [e.id, e])),
    defaultEngine: (s) => s.list.find(e => e.id === s.defaultId) ?? s.list[0],
  },
  actions: {
    async init() {
      if (this.inited) return;
      let root = await getRoot();
      // 多次重试，避免刷新早期存储未就绪导致误覆盖
      if (!root) {
        for (let i = 0; i < 5 && !root; i++) {
          await new Promise(res => setTimeout(res, 250));
          root = await getRoot();
        }
        if (!root) { root = makeInitialData(); await setRoot(root); }
      }
      const r = root as StorageModel;
      let list = Array.isArray(r.engines) ? r.engines : makeInitialData().engines;
      let curDefaultId = (r.settings?.defaultSearchId) ?? 'baidu';
      // 若默认引擎在列表中不存在，回退到第一个
      if (!list.find(e => e.id === curDefaultId)) {
        curDefaultId = list[0]?.id || 'baidu';
        const nextSettings = {
          ...(r.settings ?? makeInitialData().settings),
          defaultSearchId: curDefaultId,
        };
        await patchRoot({ settings: nextSettings } as Partial<StorageModel>);
      }
      this.list = list;
      this.defaultId = curDefaultId;
      this.inited = true;
      // 异步补全引擎图标（不阻塞初始化）
      this.ensureIcons().catch(() => {});
    },
    async reload() {
      let root = await getRoot();
      if (!root) {
        for (let i = 0; i < 5 && !root; i++) {
          await new Promise(res => setTimeout(res, 250));
          root = await getRoot();
        }
        if (!root) { root = makeInitialData(); await setRoot(root); }
      }
      const r = root as StorageModel;
      let list = Array.isArray(r.engines) ? r.engines : makeInitialData().engines;
      if (!list.length) list = makeInitialData().engines; // 保底
      const nextSettings = {
        ...(r.settings ?? makeInitialData().settings),
        defaultSearchId: list.find(e => e.id === (r.settings?.defaultSearchId))
          ? (r.settings!.defaultSearchId as string)
          : (list[0]?.id || 'baidu'),
      };
      
      // 只在设置发生变化时才写入
      if (nextSettings.defaultSearchId !== r.settings?.defaultSearchId) {
        await patchRoot({ engines: list, settings: nextSettings } as Partial<StorageModel>);
      }
      // 同步本地状态，确保界面可即时反映导入/修改后的引擎列表
      this.list = list;
      this.defaultId = nextSettings.defaultSearchId;
      this.inited = true;
      // 异步补全引擎图标
      this.ensureIcons().catch(() => {});
    },
    async setDefault(id: string) {
      // 验证搜索引擎存在
      const targetEngine = this.list.find(e => e.id === id);
      if (!targetEngine) {
        throw new Error(`搜索引擎不存在: ${id}`);
      }
      
      // 同时更新两个store的状态，确保一致性
      const root = (await getRoot()) ?? makeInitialData();
      const nextSettings = { ...(root as StorageModel).settings, defaultSearchId: id } as StorageModel['settings'];
      await patchRoot({ settings: nextSettings } as Partial<StorageModel>);
      
      // 更新本地状态 - 强制触发响应式更新
      this.defaultId = id;
      
      // 通知settings store更新（如果已初始化）
      const settingsStore = useSettings();
      if (settingsStore.inited) {
        settingsStore.settings.defaultSearchId = id;
        // 触发响应式（防御性）
        settingsStore.$patch({});
      }
      
      // 强制触发Vue响应式更新
      this.$patch({});
      
      try{
        const toast = (window as any).gceToast;
        if (typeof toast === 'function') toast(`已切换至：${targetEngine.name}`);
        else LOGI('ENG', `default changed to: ${targetEngine.name} (${id})`);
      }catch(e){ LOGW('ENG', 'toast failed', e); }
    },
    async add(engine: Omit<SearchEngine, 'id'>) {
      if (!isValidTemplate(engine.template)) throw new Error('模板必须包含 %s');
      const e: SearchEngine = { ...engine, id: uid('se-') };
      // 尝试拉取图标
      try { e.icon = await fetchEngineIconByTemplate(e.template); } catch {}
      const root = (await getRoot()) ?? makeInitialData();
      const next = [...(((root as StorageModel).engines ?? [])), e];
      await patchRoot({ engines: next } as Partial<StorageModel>);
      this.list.push(e);
    },
    async update(id: string, patch: Partial<SearchEngine>) {
      if (patch.template && !isValidTemplate(patch.template)) throw new Error('模板必须包含 %s');
      const root = (await getRoot()) ?? makeInitialData();
      let next = (root as StorageModel).engines.map((e) => e.id === id ? { ...e, ...patch } : e);
      // 若修改了模板且当前无图标，则尝试抓取
      try {
        const target = next.find(e => e.id === id);
        if (target && (!target.icon || (patch.template && patch.template !== undefined))) {
          const icon = await fetchEngineIconByTemplate(target.template);
          if (icon) {
            target.icon = icon;
            next = next.map(e => e.id === id ? target! : e);
          }
        }
      } catch {}
      await patchRoot({ engines: next } as Partial<StorageModel>);
      this.list = this.list.map((e) => e.id === id ? { ...e, ...patch } : e);
      // 同步 icon（若有）
      const maybe = next.find(e => e.id === id);
      if (maybe?.icon) this.list = this.list.map(e => e.id === id ? { ...e, icon: maybe.icon } as SearchEngine : e);
    },
    async remove(id: string) {
      const root = (await getRoot()) ?? makeInitialData();
      const next = (root as StorageModel).engines.filter(e => e.id !== id);
      await patchRoot({ engines: next } as Partial<StorageModel>);
      this.list = this.list.filter(e => e.id !== id);
      if (this.defaultId === id && this.list.length) {
        await this.setDefault(this.list[0].id);
      }
    },
    async ensureIcons() {
      try {
        const updated: SearchEngine[] = [];
        let dirty = false;
        for (const it of this.list) {
          if (!it.icon) {
            const icon = await fetchEngineIconByTemplate(it.template);
            if (icon) {
              updated.push({ ...it, icon });
              dirty = true;
            } else {
              updated.push(it);
            }
          } else {
            updated.push(it);
          }
        }
        if (dirty) {
          await patchRoot({ engines: updated } as Partial<StorageModel>);
          this.list = updated;
        }
      } catch (e) {
        // 忽略抓取失败
      }
    }
  }
});
